#ifndef BUILD_DEFS_H
#define BUILD_DEFS_H

// Based on http://stackoverflow.com/a/16469357/2179987

// Example of __DATE__ string: "Jul 27 2012"
// Example of __TIME__ string: "21:06:19"

#define COMPUTE_BUILD_YEAR \
    ( \
        (__DATE__[ 7] - '0') * 1000 + \
        (__DATE__[ 8] - '0') *  100 + \
        (__DATE__[ 9] - '0') *   10 + \
        (__DATE__[10] - '0') \
    )


#define COMPUTE_BUILD_DAY \
    ( \
        ((__DATE__[4] >= '0') ? (__DATE__[4] - '0') * 10 : 0) + \
        (__DATE__[5] - '0') \
    )


#define BUILD_MONTH_IS_JAN (__DATE__[0] == 'J' && __DATE__[1] == 'a' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_FEB (__DATE__[0] == 'F')
#define BUILD_MONTH_IS_MAR (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'r')
#define BUILD_MONTH_IS_APR (__DATE__[0] == 'A' && __DATE__[1] == 'p')
#define BUILD_MONTH_IS_MAY (__DATE__[0] == 'M' && __DATE__[1] == 'a' && __DATE__[2] == 'y')
#define BUILD_MONTH_IS_JUN (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'n')
#define BUILD_MONTH_IS_JUL (__DATE__[0] == 'J' && __DATE__[1] == 'u' && __DATE__[2] == 'l')
#define BUILD_MONTH_IS_AUG (__DATE__[0] == 'A' && __DATE__[1] == 'u')
#define BUILD_MONTH_IS_SEP (__DATE__[0] == 'S')
#define BUILD_MONTH_IS_OCT (__DATE__[0] == 'O')
#define BUILD_MONTH_IS_NOV (__DATE__[0] == 'N')
#define BUILD_MONTH_IS_DEC (__DATE__[0] == 'D')


#define COMPUTE_BUILD_MONTH \
    ( \
        (BUILD_MONTH_IS_JAN) ?  1 : \
        (BUILD_MONTH_IS_FEB) ?  2 : \
        (BUILD_MONTH_IS_MAR) ?  3 : \
        (BUILD_MONTH_IS_APR) ?  4 : \
        (BUILD_MONTH_IS_MAY) ?  5 : \
        (BUILD_MONTH_IS_JUN) ?  6 : \
        (BUILD_MONTH_IS_JUL) ?  7 : \
        (BUILD_MONTH_IS_AUG) ?  8 : \
        (BUILD_MONTH_IS_SEP) ?  9 : \
        (BUILD_MONTH_IS_OCT) ? 10 : \
        (BUILD_MONTH_IS_NOV) ? 11 : \
        (BUILD_MONTH_IS_DEC) ? 12 : \
        /* error default */  99 \
    )

#define COMPUTE_BUILD_HOUR ((__TIME__[0] - '0') * 10 + __TIME__[1] - '0')
#define COMPUTE_BUILD_MIN  ((__TIME__[3] - '0') * 10 + __TIME__[4] - '0')
#define COMPUTE_BUILD_SEC  ((__TIME__[6] - '0') * 10 + __TIME__[7] - '0')


#define BUILD_DATE_IS_BAD (__DATE__[0] == '?')

#define BUILD_YEAR  ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_YEAR)
#define BUILD_MONTH ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_MONTH)
#define BUILD_DAY   ((BUILD_DATE_IS_BAD) ? 99 : COMPUTE_BUILD_DAY)

#define BUILD_TIME_IS_BAD (__TIME__[0] == '?')

#define BUILD_HOUR  ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_HOUR)
#define BUILD_MIN   ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_MIN)
#define BUILD_SEC   ((BUILD_TIME_IS_BAD) ? 99 :  COMPUTE_BUILD_SEC)



#define DAYS_SINCE_EPOCH (DateCalculator::Days(BUILD_YEAR, BUILD_MONTH, BUILD_DAY, 2000, 1, 1))
#define SECONDS_SINCE_MIDNIGHT (BUILD_HOUR * 60 * 60 + BUILD_MIN * 60 + BUILD_SEC)




class DateCalculator
{
public:
	// Based on http://www.dreamincode.net/forums/topic/177600-calculate-the-number-of-days-in-between-two-dates/
	static int Days(int first_year, int first_month, int first_day, int second_year, int second_month, int second_day)
	{
		int days_in_months [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

		int years_difference, days_difference;
		int months_total;

		int reg_year = 365;


		/////////////////////////////Years/////////////////////////////////

		if (first_year == second_year)
			years_difference = 0;
		else
		{
			if (first_year % 4 == 0 && first_year % 100 != 0 || first_year % 400 == 0)
			{
				if (second_year % 4 == 0 && second_year % 100 != 0 || second_year % 400 == 0)
				{
					if (first_year > second_year)
						years_difference = (first_year - second_year) * (reg_year) +2;
					else
						years_difference = (second_year - first_year) * (reg_year) +2;

					if (second_month > first_month)
						if (days_in_months[first_month - 1] > days_in_months[1])
							--years_difference;
				}
				else
				{
					if (first_year > second_year)
						years_difference = (first_year - second_year) * (reg_year) +1;
					else
						years_difference = (second_year - first_year) * (reg_year) +1;

					if (first_month > second_month)
						if (days_in_months[second_month - 1] > days_in_months[1])
							--years_difference;
				}
			}
			else
			{
				if (first_year > second_year)
					years_difference = (first_year - second_year) * (reg_year);
				else
					years_difference = (second_year - first_year) * (reg_year);
			}
		}



		/////////////////////////////Months////////////////////////////////////

		if (first_month == second_month)
			months_total = 0;
		else
		{
			if (first_month > second_month)
			{
				for (int i = (first_month - 1); i > (second_month - 1); i--)
				{
					static int months_total_temp = 0;
					months_total_temp += days_in_months[i];
					months_total = months_total_temp;
				}
			}
			else
			{
				for (int i = (first_month - 1); i < (second_month - 1); i++)
				{
					static int months_total_temp = 0;
					months_total_temp += days_in_months[i];
					months_total = months_total_temp;
				}
			}
		}



		////////////////////////////Days//////////////////////////////////

		int days_total;

		if (first_day == second_day)
		{
			days_difference = 0;
			days_total = (years_difference + months_total) - days_difference;
		}
		else
		{
			if (first_day > second_day)
			{
				days_difference = first_day - second_day;
				days_total = (years_difference + months_total) - days_difference;
			}
			else
			{
				days_difference = second_day - first_day;
				days_total = (years_difference + months_total) + days_difference;
			}
		}



		//////////////////////////In Between Leap Years///////////////////////////////

		if (first_year == second_year)
		{
		}
		else
		{
			if (first_year > second_year)
			{
				for (int i = (second_year + 1); i < first_year; i++)
				{
					if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
						++days_total;
				}
			}
			else
			{
				for (int i = (first_year + 1); i < second_year; i++)
				{
					if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0)
						++days_total;
				}
			}
		}

		return days_total;
	}
};

#endif
